﻿using ActionsJudge;
using DataType;
using DataType.Actions;
using DataType.CustomEnumType;
using DataType.JudgeResults;
using DataType.MessageType;
using MapCalclator;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OprsSimulator.Operators;
using OprsSimulator.OprAttributes;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Policy;
using static System.Collections.Specialized.BitVector32;

namespace GameEvolve
{
    public class GameEvolver
    {
        /// <summary>
        /// 构造函数从文件中读取相关的信息（想定、地图）
        /// 根据文件信息为属性赋值
        /// </summary>
        public GameEvolver(string scenario_path, string map_path, string shoot_judge_table_path)
        {
            string[] scenario_file = Directory.GetFiles(scenario_path, "*.json", SearchOption.TopDirectoryOnly);    //取出当前目录下的全部.json文件
            if (scenario_file.Length == 1)
            {
                using (StreamReader r = new StreamReader(scenario_file[0]))
                {
                    string origin_scenario_data = r.ReadToEnd();
                    Dictionary<string, object> scenario_data = JsonConvert.DeserializeObject<Dictionary<string, object>>(origin_scenario_data);
                    ObservationMsg curObservation = new ObservationMsg();
                    curObservation.operators = JsonConvert.DeserializeObject<List<OperatorMsg>>(scenario_data["operators"].ToString());
                    curObservation.passengers = new List<OperatorMsg>();
                    curObservation.cities = JsonConvert.DeserializeObject<CityMsg[]>(scenario_data["cities"].ToString());
                    curObservation.actions = new List<ActionMsg>();
                    curObservation.valid_actions = new Dictionary<int, Dictionary<int, List<ActionMsg>>>();//UpdateValidActions();需要observation.operators和observation.cities 在后面调用方法初始化
                    curObservation.judge_info = new List<JudgeInfoMsg>();
                    //在更新分数之前求出最大分数
                    foreach (OperatorMsg opr in curObservation.operators)
                    {
                        if (opr.color == (int)Color.Red)
                        {
                            red_remain_max += (opr.value * opr.max_blood);
                        }
                        else if (opr.color == (int)Color.Blue)
                        {
                            blue_remain_max += (opr.value * opr.max_blood);
                        }
                    }
                    curObservation.scores = UpdateScores(curObservation.operators, curObservation.passengers, curObservation.cities);                   
                    curObservation.time = JsonConvert.DeserializeObject<TimeMsg>(scenario_data["time"].ToString());
                    observation = curObservation;
                }
            }
            else throw new Exception($"想定文件路径中没有或者有多个.json文件");
            // 读取地图数据
            Map = new Map(map_path);
            // 用结构体构造具体的算子对象
            oprsSim = new OprsSimulator.OprsSimulator();
            foreach (OperatorMsg operatorMsg in observation.operators)
            {
                if (Enum.TryParse<OprSubType>(operatorMsg.sub_type.ToString(), out OprSubType sub_type))
                {
                    IOperator opr = (IOperator)Activator.CreateInstance(Type.GetType("OprsSimulator.Operators." + sub_type.ToString() + "Opr, OprsSimulator")); //"Namespace.TypeName, AssemblyName"    命名空间.类名, 程序集名字
                    opr.SetUp(operatorMsg);
                    oprsSim.Operators.Add(opr);
                }
                else Trace.TraceError($"算子类型{operatorMsg.sub_type.ToString()}不存在！");
            }
            // 区分operators和passengers
            oprsSim.AssignOperators();
            // 初始化
            observation.operators = GetOprMsgs(oprsSim.Operators);
            observation.passengers = GetOprMsgs(oprsSim.Passengers);
            observation.valid_actions = UpdateValidActions();
            // 从文件中读取射击裁决表
            shootJudgeTab = new ShootJudgeTable(shoot_judge_table_path);

            // 此处更新FullObservation
            FullObservation = PartitionObservation(observation);
            done = false;
            replayData = new List<ObservationMsg> { observation };
        }

        private OprsSimulator.OprsSimulator oprsSim;
        public OprsSimulator.OprsSimulator OprsSim { get => oprsSim; set => oprsSim = value; }

        private List<IOperator> oprs;
        public List<IOperator> Oprs { get => oprs; set => oprs = value; }

        private List<IOperator> passengers;
        public List<IOperator> Passengers { get => passengers; set => passengers = value; }

        private Map map;
        public Map Map { get => map; set => map = value; }

        private ObservationMsg observation;
        public ObservationMsg Observation { get => observation; set => observation = value; }

        private Dictionary<int, ObservationMsg> fullObservation;
        public Dictionary<int, ObservationMsg> FullObservation { get => fullObservation; set => fullObservation = value; }

        private ShootJudgeTable shootJudgeTab;  // 射击裁决表（射击裁决使用）

        private bool done;  // 推演结束的标志
        public bool Done { get => done; set => done = value; }

        private List<ObservationMsg> replayData;// 存储复盘数据
        public List<ObservationMsg> ReplayData { get => replayData; set => replayData = value; }

        private int blue_remain_max;
        private int red_remain_max;

        public void Step(List<ActionMsg> actMsgs)
        {
            List<ActionMsg> newActionMsg = UpdateActions(actMsgs);
            List<IBasicAction> actions = GetActions(newActionMsg);

            // 1. 对actions进行裁决，形成裁决结果，分发给operators
            oprs = oprsSim.Operators;
            passengers = oprsSim.Passengers;
            List<IJudgeResult> judgeResults = new List<IJudgeResult>();
            judgeResults = ActionsJudge.ActionsJudge.ToJudge(actions, oprs, passengers, map, observation.cities, shootJudgeTab);

            // 2. 各算子更新独立属性

            OprsSim.UpdateStandalone(judgeResults, map);
            // 更新oprs字段
            for (int i = 0; i < oprsSim.Operators.Count; i++)
            {
                for (int j = 0; j < oprs.Count; j++)
                {
                    if (oprsSim.Operators[i].ObjID == oprs[j].ObjID)
                    {
                        oprs[j] = oprsSim.Operators[i];
                        break;
                    }
                }
            }
            // 乘客更新属性
            oprsSim.UpdatePassengers(judgeResults, oprs, map);
            // 重新分配算子
            oprsSim.AssignOperators();
            // 更新oprs字段
            for (int i = 0; i < oprsSim.Operators.Count; i++)
            {
                for (int j = 0; j < oprs.Count; j++)
                {
                    if (oprsSim.Operators[i].ObjID == oprs[j].ObjID)
                    {
                        oprs[j] = oprsSim.Operators[i];
                        break;
                    }
                }
            }
            // 更新passengers字段
            for (int i = 0; i < oprsSim.Passengers.Count; i++)
            {
                for (int j = 0; j < passengers.Count; j++)
                {
                    if (oprsSim.Passengers[i].ObjID == passengers[j].ObjID)
                    {
                        passengers[j] = oprsSim.Passengers[i];
                        break;
                    }
                }
            }

            // 3. 各算子更新交叉属性

            OprsSim.UpdateAssociated(oprs, map);
            // 更新oprs字段
            for(int i = 0; i < oprsSim.Operators.Count; i++)
            {
                for (int j = 0; j < oprs.Count; j++)
                {
                    if (oprsSim.Operators[i].ObjID == oprs[j].ObjID)
                    {
                        oprs[j] = oprsSim.Operators[i];
                        break;
                    }
                }
            }

            // 4. 更新其它态势信息

            ObservationMsg curObservation = new ObservationMsg();
            curObservation.operators = GetOprMsgs(oprs);
            curObservation.passengers = GetOprMsgs(passengers);
            curObservation.cities = UpdateCities(judgeResults);
            curObservation.actions = actMsgs;
            curObservation.valid_actions = UpdateValidActions();
            curObservation.judge_info = UpdateJudgeInfo(judgeResults);
            curObservation.scores = UpdateScores(curObservation.operators, curObservation.passengers, curObservation.cities);
            curObservation.time = UpdateTime();
            observation = curObservation;

            FullObservation = PartitionObservation(observation);

            replayData.Add(observation);
            //导出replay data.json文件
            if (done)
            {
                //D:\C#\wargame-for-distribution\WargameEngine\bin\Debug    ..\表示返回到上一级目录    ..\\..\\..\\..\\Replay data\\  或者  \\..\\..\\..\\Replay data\\  都可以
                string replayDataDir = Directory.GetCurrentDirectory() + "\\..\\..\\..\\Replay data\\";
                if (!Directory.Exists(replayDataDir))
                {
                    Directory.CreateDirectory(replayDataDir);
                }
                //Formatting.Indented参数用于在生成的JSON字符串中添加缩进和换行符
                string json = JsonConvert.SerializeObject(replayData, Formatting.Indented);
                string fileName = "replay_" + DateTime.Now.ToString("yyyyMMddHHmm") + ".json";
                File.WriteAllText(replayDataDir + fileName, json);
            }
        }

        /// <summary>
        /// 根据oprs的信息，更新valid_actions
        /// </summary>
        private Dictionary<int, Dictionary<int, List<ActionMsg>>> UpdateValidActions()
        {
            return oprsSim.ConfirmValidActions(observation.operators, observation.cities, map, shootJudgeTab);
        }

        /// <summary>
        /// 从judgeResults中选出与shoot有关的，形成judge_info
        /// </summary>
        private List<JudgeInfoMsg> UpdateJudgeInfo(List<IJudgeResult> judgeResults)
        {
            // 射击裁决cur_step
            List<JudgeInfoMsg> judge_infos = new List<JudgeInfoMsg>();
            foreach (IJudgeResult judge_result in judgeResults)
            {
                if (judge_result.ActionType == ActionType.Shoot && judge_result.IsSuccess)
                {
                    //if ((bool)judge_result.GetType().GetProperty("IsShooting").GetValue(judge_result))
                    //{
                    ShootingJudgeResult shootingJudgeResult = (ShootingJudgeResult)judge_result;

                    JudgeInfoMsg judgeInfoMsg = new JudgeInfoMsg
                    {
                        att_level = shootingJudgeResult.AttLevel,
                        att_obj_blood = shootingJudgeResult.AttObjBlood,
                        att_obj_id = shootingJudgeResult.ObjID,
                        attack_color = (int)shootingJudgeResult.AttackColor,
                        attack_sub_type = (int)shootingJudgeResult.AttackSubType,
                        cur_step = observation.time.cur_step,
                        damage = shootingJudgeResult.Damage,
                        distance = shootingJudgeResult.Distance,
                        ele_diff = shootingJudgeResult.EleDiff,
                        ori_damage = shootingJudgeResult.OriDamage,
                        random1 = shootingJudgeResult.Random1,
                        random2 = shootingJudgeResult.Random2,
                        random2_rect = shootingJudgeResult.Random2Rect,
                        rect_damage = shootingJudgeResult.RectDamage,
                        target_color = (int)shootingJudgeResult.TargetColor,
                        target_obj_id = shootingJudgeResult.TargetObjID,
                        target_sub_type = (int)shootingJudgeResult.TargetSubType,
                        type = (int)shootingJudgeResult.Type,
                        wp_id = (int)shootingJudgeResult.WeaponID
                    };
                    judge_infos.Add(judgeInfoMsg);
                   // }
                }
            }
            return judge_infos;
        }

        private TimeMsg UpdateTime()
        {
            TimeMsg timeMsg = new TimeMsg 
            {
                cur_step = observation.time.cur_step,
                tick = observation.time.tick,
                max_time = observation.time.max_time
            };
            timeMsg.cur_step++;
            if (timeMsg.cur_step >= timeMsg.max_time) done = true;
            else done = false;
            return timeMsg;
        }

        /// <summary>
        /// 根据裁决结果更新分数
        /// </summary>
        private ScoreMsg UpdateScores(List<OperatorMsg> operators, List<OperatorMsg> passengers, CityMsg[] cities)
        {
            // 初始化scores
            ScoreMsg cur_scores = new ScoreMsg();
            int blue_remain_max = this.blue_remain_max;
            int red_remain_max = this.red_remain_max;

            cur_scores.blue_attack = 0;
            cur_scores.blue_occupy = 0;
            cur_scores.blue_remain = 0;
            cur_scores.blue_remain_max = blue_remain_max;
            cur_scores.blue_total = 0;
            cur_scores.blue_win = 0;
            cur_scores.red_attack = 0;
            cur_scores.red_occupy = 0;
            cur_scores.red_remain = 0;
            cur_scores.red_remain_max = red_remain_max;
            cur_scores.red_total = 0;
            cur_scores.red_win = 0;

            // ===计算当前所有的得分===
            // 算子分数
            foreach (OperatorMsg opr in operators)
            {
                if (opr.color == (int)Color.Red)
                {
                    cur_scores.red_remain += (opr.value * opr.blood);
                }
                else if (opr.color == (int)Color.Blue)
                {
                    cur_scores.blue_remain += (opr.value * opr.blood);
                }               
            }
            foreach (OperatorMsg opr in passengers)
            {
                if (opr.color == (int)Color.Red)
                {
                    cur_scores.red_remain += (opr.value * opr.blood);
                }
                else if (opr.color == (int)Color.Blue)
                {
                    cur_scores.blue_remain += (opr.value * opr.blood);
                }
            }
            // 夺控点分数
            foreach (CityMsg city in cities)
            {
                if (city.flag == (int)Color.Red)
                {
                    cur_scores.red_occupy += city.value;
                }
                else if (city.flag == (int)Color.Blue)
                {
                    cur_scores.blue_occupy += city.value;
                }
            }
            cur_scores.blue_attack = cur_scores.red_remain_max - cur_scores.red_remain;
            cur_scores.red_attack = cur_scores.blue_remain_max - cur_scores.blue_remain;
            cur_scores.blue_total = cur_scores.blue_attack + cur_scores.blue_occupy;
            cur_scores.red_total = cur_scores.red_attack + cur_scores.red_occupy;
            cur_scores.blue_win = cur_scores.blue_total - cur_scores.red_total;
            cur_scores.red_win = -cur_scores.blue_win;

            return cur_scores;
        }

        /// <summary>
        /// 根据夺控的裁决结果更新夺控点信息
        /// </summary>
        private CityMsg[] UpdateCities(List<IJudgeResult> judgeResults)
        {
            //夺控裁决结果更新
            CityMsg[] cities = new CityMsg[observation.cities.Length];
            for (int i = 0; i < observation.cities.Count(); i++)
            {
                CityMsg city = new CityMsg
                {
                    coord = observation.cities[i].coord,
                    value = observation.cities[i].value,
                    name = observation.cities[i].name,
                    flag = observation.cities[i].flag
                };
                cities[i] = city;
            }
            foreach (var judge_result in judgeResults)
            {
                if (judge_result.ActionType == ActionType.Occupy && judge_result.IsSuccess)
                {
                    OccupyJudgeResult occupyJudgeResult = (OccupyJudgeResult)judge_result;                    
                    for (int i = 0; i < cities.Count(); i++)
                    {
                        if (occupyJudgeResult.CityCoord == cities[i].coord)
                        {
                            cities[i].flag = (int)occupyJudgeResult.OprColor;
                        }
                    }
                }
            }
            return cities;
        }

        private List<OperatorMsg> GetOprMsgs(List<IOperator> oprs)
        {
            List<OperatorMsg> oprMsgs = new List<OperatorMsg>();

            //foreach (var opr in oprs)
            for (int i = 0; i < oprs.Count; i++)
            {
                IOperator opr = oprs[i];
                OperatorMsg operatorMsg = new OperatorMsg();
                PropertyInfo[] properties = opr.GetType().GetProperties();  //算子类的全部属性
                FieldInfo[] msgFieldInfos = typeof(OperatorMsg).GetFields();   //算子数据结构的全部成员
                object boxedOperatorMsg = operatorMsg;      //装箱    （结构体是值类型，不是引用类型）
                foreach (var property in properties)
                {
                    foreach (var msgFieldInfo in msgFieldInfos)
                    {
                        //Type type = msgFieldInfo.FieldType;
                        //Type type = property.PropertyType;
                        if (msgFieldInfo.Name.Replace("_", "").ToLower() == property.Name.ToLower())    // 字符串字母全部改成小写，去除下划线（属性大写，无下划线）
                        {
                            if (property.Name == "CarryWeaponIDs")
                            {
                                List<int> carry_weapon_ids = new List<int>();
                                foreach (WeaponType id in (List<WeaponType>)property.GetValue(opr))
                                {
                                    carry_weapon_ids.Add((int)id);
                                    //operatorMsg.carry_weapon_ids = carry_weapon_ids.ToArray();
                                    msgFieldInfo.SetValue(boxedOperatorMsg, carry_weapon_ids.ToArray());
                                }
                                continue;
                            }
                            if (property.Name == "RemainBulletNums")
                            {
                                Dictionary<int, int> remain_bullet_nums = new Dictionary<int, int>();
                                foreach (var remain_bullet_num in (Dictionary<BulletType, int>)property.GetValue(opr))
                                {
                                    remain_bullet_nums.Add((int)remain_bullet_num.Key, remain_bullet_num.Value);
                                    msgFieldInfo.SetValue(boxedOperatorMsg, remain_bullet_nums);
                                }
                                continue;
                            }
                            if (property.Name == "RemainBulletNumsBK")
                            {
                                Dictionary<int, int> remain_bullet_nums_bk = new Dictionary<int, int>();
                                foreach (var remain_bullet_num_bk in (Dictionary<BulletType, int>)property.GetValue(opr))
                                {
                                    remain_bullet_nums_bk.Add((int)remain_bullet_num_bk.Key, remain_bullet_num_bk.Value);
                                    msgFieldInfo.SetValue(boxedOperatorMsg, remain_bullet_nums_bk);
                                }
                                continue;
                            }
                            if (property.Name == "ValidPassengerTypes")
                            {
                                List<int> valid_passenger_types = new List<int>();
                                foreach (var type in (List<OprSubType>)property.GetValue(opr))
                                {
                                    valid_passenger_types.Add((int)type);
                                    msgFieldInfo.SetValue(boxedOperatorMsg, valid_passenger_types);
                                }
                                continue;
                            }
                            if (property.Name == "MaxPassengerNums")
                            {
                                Dictionary<int, int> max_passenger_nums = new Dictionary<int, int>();
                                foreach (var num in (Dictionary<OprSubType, int>)property.GetValue(opr))
                                {
                                    max_passenger_nums.Add((int)num.Key, num.Value);
                                    msgFieldInfo.SetValue(boxedOperatorMsg, max_passenger_nums);
                                }
                                continue;
                            }
                            //if (property.Name == "MovePath")
                            //{
                            //    Console.WriteLine(property.GetValue(opr));
                            //    List<int> movePath = new List<int>();
                            //    foreach (var num in (List<int>)property.GetValue(opr))
                            //    {
                            //        Console.WriteLine(1111 + "" + property.GetValue(opr));
                            //        movePath.Add((int)num);
                            //        msgFieldInfo.SetValue(boxedOperatorMsg, movePath);
                            //    }
                            //    continue;
                            //}
                            if (property.Name == "ObserveDistance")
                            {
                                Dictionary<int, int> observeDistance = new Dictionary<int, int>();
                                foreach (var num in (Dictionary<OprSubType, int>)property.GetValue(opr))
                                {
                                    observeDistance.Add((int)num.Key, num.Value);
                                    msgFieldInfo.SetValue(boxedOperatorMsg, observeDistance);
                                }
                                continue;
                            }
                            object value = DeepCopy(property.GetValue(opr));
                            msgFieldInfo.SetValue(boxedOperatorMsg, value);
                            //msgFieldInfo.SetValue(boxedOperatorMsg, property.GetValue(opr));
                        }//消息结构体的成员个数大于等于算子属性个数
                    }
                }
                OperatorMsg unboxedOperatorMsg = (OperatorMsg)boxedOperatorMsg; //拆箱
                oprMsgs.Add(unboxedOperatorMsg);
            }

            return oprMsgs;
        }
        private object DeepCopy(object source)
        {
            if (source == null)
                return null;

            // 创建一个内存流
            MemoryStream memoryStream = new MemoryStream();

            // 创建二进制格式化器
            BinaryFormatter formatter = new BinaryFormatter();

            // 将对象序列化到内存流中
            formatter.Serialize(memoryStream, source);

            // 将内存流指针位置归零
            memoryStream.Position = 0;

            // 从内存流中反序列化为新的对象副本
            object clone = formatter.Deserialize(memoryStream);

            // 关闭内存流
            memoryStream.Close();

            return clone;
        }

        private List<IBasicAction> GetActions(List<ActionMsg> actMsgs)
        {
            List<IBasicAction> actions = new List<IBasicAction>();

            foreach (var actMsg in actMsgs)
            {
                if (Enum.TryParse<ActionType>(actMsg.type.ToString(), out ActionType actType))
                {
                    IBasicAction basicAction = (IBasicAction)Activator.CreateInstance(Type.GetType("DataType.Actions." + actType.ToString() + "Action, DataType"));
                    FieldInfo[] msgFieldInfos = typeof(ActionMsg).GetFields();  //Msg的全部成员
                    PropertyInfo[] properties = basicAction.GetType().GetProperties();   //action的全部属性

                    object o = basicAction;     //  装箱      (这个虽然也是结构体，但是试了下这个好像可以不装箱)
                    foreach (var msgFieldInfo in msgFieldInfos)
                    {
                        foreach(var property in properties)
                        {
                            if(msgFieldInfo.Name.Replace("_", "").ToLower() == property.Name.ToLower())
                            {
                                property.SetValue(o, msgFieldInfo.GetValue(actMsg));//拿消息结构体actMsg成员值，给basicAction属性赋值
                            }//Msg结构成员数大于等于basicAction属性数
                        }
                    }
                    IBasicAction basicAct = (IBasicAction)o;
                    actions.Add(basicAct);
                }else throw new Exception($"动作的类型ActionType有误！");
            }


            return actions;
        }

        private Dictionary<int, ObservationMsg> PartitionObservation(ObservationMsg observation)
        {
            Dictionary<int, ObservationMsg> fullObservation = new Dictionary<int, ObservationMsg>();

            fullObservation.Add(-1, observation);
            fullObservation.Add((int)Color.Red, AssignObservation((int)Color.Red, observation));
            fullObservation.Add((int)Color.Blue, AssignObservation((int)Color.Blue, observation));
            return fullObservation;
        }
        private ObservationMsg AssignObservation(int color, ObservationMsg observation)
        {
            List<ActionMsg> actions = new List<ActionMsg>();
            foreach (ActionMsg action in observation.actions)
            {
                OperatorMsg opr = GetOprFromID(action.obj_id, observation);
                if (opr.color == color)
                {
                    actions.Add(action);
                }
            }

            // 更新valid_actions
            Dictionary<int, Dictionary<int, List<ActionMsg>>> valid_actions = new Dictionary<int, Dictionary<int, List<ActionMsg>>>();
            foreach (KeyValuePair<int, Dictionary<int, List<ActionMsg>>> opr_actions in observation.valid_actions)
            {
                int obj_id = opr_actions.Key;
                Dictionary<int, List<ActionMsg>> individual_valid_actions = opr_actions.Value;
                OperatorMsg opr = GetOprFromID(obj_id, observation);
                if (opr.color == color)
                {
                    valid_actions.Add(obj_id, individual_valid_actions);
                }
            }

            // 更新operators
            List<OperatorMsg> operators = new List<OperatorMsg>();
            List<OperatorMsg> our_operators = new List<OperatorMsg>();
            List<OperatorMsg> enemies = new List<OperatorMsg>();
            foreach (OperatorMsg opr in observation.operators)
            {
                if (opr.color == color)
                {
                    operators.Add(opr);
                    our_operators.Add(opr);
                }
                else
                {
                    enemies.Add(opr);
                }
            }
            for (int i = 0; i < enemies.Count; i++)
            {
                OperatorMsg enemy = enemies[i];
                bool can_be_seen = false;
                foreach (OperatorMsg opr in our_operators)
                {
                    if (opr.see_enemy_bop_ids.Contains(enemy.obj_id))
                    {
                        can_be_seen = true;
                        break;
                    }
                }
                if (can_be_seen)  // 能被看见的情况，隐藏迷雾属性
                {
                    enemy.remain_bullet_nums = new Dictionary<int, int> { { 0, -1 }, { 100, -1 }, { 101, -1 }, { 102, -1 } };
                    enemy.move_to_stop_remain_time = -1;
                    enemy.can_to_move = false;
                    if (enemy.move_path == null) enemy.move_path = new List<int>();
                    else enemy.move_path.Clear();
                    enemy.tire_accumulate_time = -1;
                    enemy.keep_remain_time = -1;
                    enemy.launcher = -1;
                    if (enemy.passenger_ids == null) enemy.passenger_ids = new List<int>();
                    else enemy.passenger_ids.Clear();
                    if (enemy.launch_ids == null) enemy.launch_ids = new List<int>();
                    else enemy.launch_ids.Clear();
                    enemy.alive_remain_time = -1;
                    enemy.get_on_remain_time = -1;
                    enemy.get_off_remain_time = -1;
                    enemy.weapon_unfold_time = -1;
                    if (enemy.see_enemy_bop_ids == null) enemy.see_enemy_bop_ids = new List<int>();
                    else enemy.see_enemy_bop_ids.Clear();
                    enemy.C2 = -1;
                    enemy.C3 = -1;
                    enemy.target_state = -1;
                    operators.Add(enemy);
                }
            }

            // 更新CurObservation[color]
            ObservationMsg observationMsg = new ObservationMsg
            {
                cities = observation.cities,
                scores = observation.scores,
                time = observation.time,
                judge_info = observation.judge_info,
                actions = actions,
                valid_actions = valid_actions,
                operators = operators
            };
            return observationMsg;
        }
        private OperatorMsg GetOprFromID(int obj_id, ObservationMsg observation)
        {
            foreach (OperatorMsg opr in observation.operators)
            {
                if (opr.obj_id == obj_id) return opr;
            }
            Trace.TraceWarning($"GetOprFromID失败:态势中没有ID为{obj_id}的算子");
            return new OperatorMsg();
        }
        private List<ActionMsg> UpdateActions(List<ActionMsg> actions)
        {
            List<ActionMsg> actionMsgs = new List<ActionMsg>();
            // 去除对单个算子的重复或多个动作
            List<ActionMsg> remove_actions = new List<ActionMsg>();
            List<int> oprs_id = new List<int>();
            for (int i = 0; i < actions.Count; i++)
            {
                if (oprs_id.Contains(actions[i].obj_id)) continue;
                oprs_id.Add(actions[i].obj_id);
                for (int j = i + 1; j < actions.Count; j++)
                {                  
                    if (actions[i].obj_id == actions[j].obj_id)
                    {
                        remove_actions.Add(actions[j]);
                        Trace.TraceWarning($"无效指令：对{actions[i].obj_id}算子下达了多条动作指令");
                    }
                }                
            }
            foreach (ActionMsg remove_action in remove_actions) { actions.Remove(remove_action); }
            

            foreach (ActionMsg action in actions)
            {
                // 当前动作要在valid_actions中
                if (observation.valid_actions.TryGetValue(action.obj_id, out Dictionary<int, List<ActionMsg>> opr_valid_actions))     
                {
                    if (opr_valid_actions.TryGetValue(action.type, out List<ActionMsg> list_a))
                    {
                        if (list_a.Count > 0)
                        {
                            if (action.type == (int)ActionType.Move)
                            {
                                actionMsgs.Add(action);
                            }
                            else if (action.type == (int)ActionType.Shoot)
                            {
                                foreach (ActionMsg a in list_a)
                                {
                                    if (action.target_obj_id == a.target_obj_id && action.weapon_id == a.weapon_id)
                                    {
                                        actionMsgs.Add(action);
                                        break;
                                    }
                                }
                            }
                            else if (action.type == (int)ActionType.Occupy)
                            {
                                actionMsgs.Add(action);
                            }
                            else if (action.type == (int)ActionType.StopMove)
                            {
                                actionMsgs.Add(action);
                            }
                            else if (action.type == (int)ActionType.WeaponLock)
                            {
                                actionMsgs.Add(action);
                            }
                            else if (action.type == (int)ActionType.WeaponUnfold)
                            {
                                actionMsgs.Add(action);
                            }
                            else if (action.type == (int)ActionType.ChangeState)
                            {
                                actionMsgs.Add(action);
                            }
                            else if (action.type == (int)ActionType.GetOn)
                            {
                                actionMsgs.Add(action);
                            }
                            else if (action.type == (int)ActionType.GetOff)
                            {
                                actionMsgs.Add(action);
                            }
                            else
                            {
                                Trace.TraceWarning($"传入的动作类型有错误: {action.type}");
                            }
                        }
                    }
                }
            }

            return actionMsgs;
        }
    }
}
